﻿using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using MouseKeyboardLibrary;

namespace ColorPicker
{
    public partial class MainForm : Form
    {

        [DllImport("user32.dll")]
        private static extern IntPtr GetDC(IntPtr hwnd);

        [DllImport("gdi32.dll")]
        private static extern int GetPixel(IntPtr hdc, Point p);

        [DllImport("user32.dll")]
        public static extern bool GetCursorPos(out Point pt);

        [DllImport("user32.dll")]
        public static extern void SetCursorPos(int x, int y);

        private int WindowBehaviourConfig;
        private bool isShowMagnifier;

        private MouseHook mouseHook;
        private KeyboardHook keyboardHook;

        public MainForm()
        {
            InitializeComponent();
            WindowBehaviourConfig = ConfigHelper.getWindowBehaviourConfig();
            isShowMagnifier = ConfigHelper.isShowMagnifier();
            mouseHook = new MouseHook();
            keyboardHook = new KeyboardHook();
        }

        private void button_settings_Click(object sender, EventArgs e)
        {
            SettingsForm sf = new SettingsForm(WindowBehaviourConfig, isShowMagnifier);
            sf.onConfirm += new SettingsForm.ConfirmHandler(onConfirm);
            DialogResult dr = sf.ShowDialog(this);
            if(dr != DialogResult.Abort)
            {
                sf.Dispose();
            }
        }

        private void onConfirm(int i, bool b)
        {
            WindowBehaviourConfig = i;
            isShowMagnifier = b;
        }

        private void button_start_Click(object sender, EventArgs e)
        {
            switch (WindowBehaviourConfig)
            {
                case ConfigHelper.TAG_IS_FOLLOW_MOUSE:
                    FormBorderStyle = FormBorderStyle.None;
                    break;
                case ConfigHelper.TAG_IS_MINIMIZE:
                    WindowState = FormWindowState.Minimized;
                    break;
                case ConfigHelper.TAG_NONE_OF_ALL:
                default:
                    break;
            }

            mouseHook.MouseDown += new MouseEventHandler(mouseHook_MouseDown);
            mouseHook.MouseMove += new MouseEventHandler(mouseHook_MouseMove);
            keyboardHook.KeyUp += new KeyEventHandler(keyboardHook_KeyUp);
            mouseHook.Start();
            keyboardHook.Start();
        }

        private void mouseHook_MouseDown(object sender, MouseEventArgs e)
        {
            pickColor();
        }

        private void pickColor()
        {
            mouseHook.Stop();
            keyboardHook.Stop();

            switch (WindowBehaviourConfig)
            {
                case ConfigHelper.TAG_IS_FOLLOW_MOUSE:
                    FormBorderStyle = FormBorderStyle.FixedSingle;
                    break;
                case ConfigHelper.TAG_IS_MINIMIZE:
                    WindowState = FormWindowState.Normal;
                    break;
                case ConfigHelper.TAG_NONE_OF_ALL:
                default:
                    break;
            }
        }

        private void keyboardHook_KeyUp(object sender, KeyEventArgs e)
        {
            Point point;
            switch (e.KeyCode)
            {
                case Keys.Escape:
                    pickColor();
                    break;
                case Keys.Left:
                    GetCursorPos(out point);
                    point.X--;
                    SetCursorPos(point.X, point.Y);
                    releaseMouse(point);
                    break;
                case Keys.Right:
                    GetCursorPos(out point);
                    point.X++;
                    SetCursorPos(point.X, point.Y);
                    releaseMouse(point);
                    break;
                case Keys.Up:
                    GetCursorPos(out point);
                    point.Y--;
                    SetCursorPos(point.X, point.Y);
                    releaseMouse(point);
                    break;
                case Keys.Down:
                    GetCursorPos(out point);
                    point.Y++;
                    SetCursorPos(point.X, point.Y);
                    releaseMouse(point);
                    break;
                default:
                    break;
            }
        }

        private void mouseHook_MouseMove(object sender, MouseEventArgs e)
        {
            Point point;
            GetCursorPos(out point);
            releaseMouse(point);
        }

        private void releaseMouse(Point p)
        {
            switch (WindowBehaviourConfig)
            {
                case ConfigHelper.TAG_IS_FOLLOW_MOUSE:
                    releaseForm(p);
                    releaseColors(p);
                    break;
                case ConfigHelper.TAG_NONE_OF_ALL:
                    releaseColors(p);
                    break;
                case ConfigHelper.TAG_IS_MINIMIZE:
                default:
                    break;
            }

            TopMost = true;
        }

        private void releaseForm(Point p)
        {
            Point point = new Point(p.X + 10, p.Y + 10);
            Size size = Screen.PrimaryScreen.Bounds.Size;
            if (point.X > size.Width - this.Width)
            {
                point.X -= this.Width + 20;
            }
            if (point.Y > size.Height - this.Height)
            {
                point.Y -= this.Height + 20;
            }
            this.Location = point;
        }

        private void releaseColors(Point p)
        {
            IntPtr hdc = GetDC(new IntPtr(0));
            int color = GetPixel(hdc, p);
            int r = (color & 0xFF);
            int g = (color & 0xFF00) / 0x100;
            int b = (color & 0xFF0000) / 0x10000;

            textBox_mousePosition.Text = p.X + "," + p.Y;
            textBox_hex.Text = "#" + color.ToString("X6");
            textBox_rgb.Text = r + "," + g + "," + b;
            label_color.BackColor = Color.FromArgb(r, g, b);

            if (!isShowMagnifier) return;

            Bitmap bmp = new Bitmap(36, 24);
            Graphics graphics = Graphics.FromImage(bmp);
            graphics.CopyFromScreen(p.X - 18, p.Y - 12, 0, 0, bmp.Size);
            Image pThumbnail = bmp.GetThumbnailImage(pictureBox_magnifier.Width, pictureBox_magnifier.Height, null, new IntPtr());
            graphics.DrawImage(bmp, 18, 12, pThumbnail.Width, pThumbnail.Height);
            graphics.Dispose();
            pictureBox_magnifier.Image = pThumbnail;
            graphics = Graphics.FromImage(pictureBox_magnifier.Image);
            graphics.DrawRectangle(Pens.Black, pictureBox_magnifier.Width / 2 - 2, pictureBox_magnifier.Height / 2 - 2, 4, 4);
            graphics.Dispose();
        }
    }
}
